<template>
    <div class="dept-tree-selecter">
        <el-cascader :options="list" :props="props" clearable filterable v-model="currentVal" @change="change">
            <template slot-scope="{data}">{{getOptionDisplayText(data)}}</template>
        </el-cascader>
    </div>
</template>
<script lang="ts">
  // api
  import {ID} from '@/api/http';
  import DepartmentApi from '@/api/user/departmentApi';
  // structure
  import Department from '@/structure/department';
  import {Component, Model, Prop, Vue, Watch} from 'vue-property-decorator';

  @Component
  export default class DeptTreeSelecter extends Vue {

    @Model('change')
    @Prop({
      required: true
    })
    public value!: ID;
    @Prop({
      default: true
    })
    public clearable!: boolean;
    @Prop({
      default: false
    })
    public showNone!: boolean;
    @Prop({
      default: false
    })
    public showEmpty!: boolean;
    @Prop({
      default: '无'
    })
    public emptyLabel!: string;
    @Prop({
      default: '0'
    })
    public emptyValue!: ID;
    @Prop({
      default: null
    })
    public filter!: (dept: Department) => boolean;

    public props = {
      value: 'departmentId',
      label: 'departmentName',
      expandTrigger: 'hover',
      checkStrictly: true,
      emitPath: false
    };

    public currentVal: ID = null;
    public list: Department[] = [];
    public map: { [key: string]: Department } = {};

    public created(): void {
      this.currentVal = this.value;
      this.refresh();
    }

    @Watch('value')
    public valueChangeHandler(value: ID): void {
      this.currentVal = value;
    }

    @Watch('currentVal')
    public currentValChangeHandler(currentVal: ID): void {
      this.$emit('change', currentVal);
    }

    public getOptionDisplayText(item: Department): string {
      const texts = [];
      for (let i = 0; i < item.extLevel; i++) {
        texts.push(' - ');
      }
      texts.push(item.departmentName);
      if (item.departmentTypeName) {
        texts.push(`(${item.departmentTypeName})`);
      }
      return texts.join('');
    }

    public refresh(): void {
      DepartmentApi.tree().then((res) => {
        this.refreshByData(res);
      });
    }

    public refreshByData(res: Department[]): void {
      this.fillToMap(res);
      let list = [] as Department[];
      if (this.showNone) {
        const showNoneItem = new Department();
        showNoneItem.departmentId = null;
        showNoneItem.departmentName = '不限';
        list = list.concat(showNoneItem);
      }
      if (this.showEmpty) {
        const showEmptyItem = new Department();
        showEmptyItem.departmentId = this.emptyValue;
        showEmptyItem.departmentName = this.emptyLabel;
        list = list.concat(showEmptyItem);
      }
      list = list.concat(res);
      this.list = list;
    }

    public fillToMap(res: Department[]): void {
      if (res && res.length > 0) {
        res.forEach((department) => {
          this.map['' + department.departmentId] = department;
          this.fillToMap(department.children);
        });
      }
    }

    public handlerFilter(val: Department): boolean {
      return typeof this.filter === 'function' && this.filter(val);
    }

    public change(id: ID): void {
      const currentDepartment = this.map['' + id];
      if (currentDepartment) {
        this.$emit('choose', currentDepartment);
      }
    }
  }
</script>
<style>
    .dept-tree-selecter > * {
        width: 100%;
    }
</style>
